﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using yq.ICache;
using System.Xml.Linq;
using yq.Redis;
namespace yq
{
    /// <summary>
    /// 缓存工厂类
    /// 根据配置选择web缓存还是分布式缓存
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CaChe<T> where T : class,new()
    {
        static CaChe()
        {
            ListConfigHost = Initialization();
        }

        /// <summary>
        /// 判断类所使用的缓存
        /// </summary>
        /// <returns></returns>
        public static ConfigHost GetConfigHost()
        {
            return GetConfigHost(typeof(T).FullName);
        }

        /// <summary>
        /// 判断类所使用的缓存
        /// </summary>
        /// <param name="fullname"></param>
        /// <returns></returns>
        public static ConfigHost GetConfigHost(string fullname)
        {
            ConfigHost config = new ConfigHost();
            if (ListConfigHost.TryGetValue(fullname, out config) == false)
            {
                //如果没有 使用默认配置
                config = DefaultConfigHost;
            }
            config.FullName = fullname;

            return config;
        }


        /// <summary>
        /// 获取缓存对象
        /// </summary>
        /// <returns></returns>
        public static IClient<T> Client()
        {
            ConfigHost config = GetConfigHost();
            
            return ClientSwitch(config);
        }

        private static IClient<T> ClientSwitch(ConfigHost config)
        {
            if (config.Type == CaCheType.Redis)
            {
                return new yq.Redis.RedisClient<T>(config);
            }
            else if (config.Type == CaCheType.No)
            {
                return new yq.NoCache<T>();
            }
            else
            {
                return new yq.WebCache.WebClient<T>(config);
            }
        }


        /// <summary>
        /// 清理缓存中hash 所有值
        /// </summary>
        /// <param name="fullname">类fullname</param>
        /// <returns></returns>
        public static void RefreshDelete(string fullname)
        {
            ConfigHost config = GetConfigHost(fullname);
            ClientSwitch(config).HashRefreshDelete(fullname);
        }

        /// <summary>
        /// 清理缓存中hash的key  
        /// 根据传入的fullname作为操作类名，忽略 T
        /// </summary>
        /// <param name="fullname">类fullname</param>
        /// <param name="key">key</param>
        /// <returns></returns>
        public static void RefreshDelete(string fullname, string key)
        {
            ConfigHost config = GetConfigHost(fullname);
            ClientSwitch(config).HashRefreshDelete(fullname,key);
        }

        /// <summary>
        /// 更新缓存中hash的key  
        /// 根据传入的fullname作为操作类名，忽略 T
        /// </summary>
        /// <param name="fullname">类fullname</param>
        /// <param name="key">key</param>
        /// <returns></returns>
        public static void RefreshLoad(string fullname, string key, object obj)
        {
            ConfigHost config = GetConfigHost(fullname);
            ClientSwitch(config).HashRefreshLoad(fullname, key, obj);
        }

        /// <summary>
        /// 配置列表
        /// </summary>
        private static Dictionary<string, ConfigHost> ListConfigHost { set; get; }

        /// <summary>
        /// 默认配置
        /// </summary>
        private static ConfigHost DefaultConfigHost { set; get; }


        /// <summary>
        /// 配置文件路径
        /// </summary>
        private const string _DefaultFilePath = "RedisHost.config";

        /// <summary>
        /// 站点配置文件路径
        /// </summary>
        private static string _ConfigFilePath = string.Empty;
        /// <summary>
        /// 站点配置文件路径
        /// </summary>
        private static string ConfigFilePath
        {
            get
            {
                if (string.IsNullOrEmpty(_ConfigFilePath))
                {
                    _ConfigFilePath =cn.Util.WebConfig.ConfigFilePath + _DefaultFilePath;
                }

                return _ConfigFilePath;
            }
        }

        /// <summary>
        /// 初始化配置文件
        /// 从配置文件中读取表与写站点的关系
        /// </summary>
        /// <returns></returns>
        private static Dictionary<string, ConfigHost> Initialization()
        {
            Dictionary<string, ConfigHost> dics = new Dictionary<string, ConfigHost>();

            var root = XElement.Load(ConfigFilePath, LoadOptions.None);
            var allElement = from obj in root.Elements()
                             select obj;

            foreach (XElement host in allElement)
            {
                ConfigHost info = new ConfigHost();

                if (host.Name.LocalName == "Redis")
                {
                    info.Type = CaCheType.Redis ;
                }
                else if (host.Name.LocalName == "WebCache")
                {
                    info.Type = CaCheType.WebCache;
                }
                else if (host.Name.LocalName == "No")
                {
                    info.Type = CaCheType.No;
                }
                

                //取站点各信息
                info.isDefault = host.Attribute(XName.Get("isDefault")) != null && host.Attribute(XName.Get("isDefault")).Value == "true";

                string write = host.Attribute(XName.Get("write")) == null ? "" : host.Attribute(XName.Get("write")).Value;
                info.WriteCount = host.Attribute(XName.Get("writeCount")) == null ? info.WriteCount : Convert.ToInt32(host.Attribute(XName.Get("writeCount")).Value);

                string read = host.Attribute(XName.Get("read")) == null ? "" : host.Attribute(XName.Get("read")).Value;
                info.ReadCount = host.Attribute(XName.Get("readCount")) == null ? info.ReadCount : Convert.ToInt32(host.Attribute(XName.Get("readCount")).Value);

                info.ReadHosts = read.Split(',');

                //取类信息
                foreach (XElement cla in host.Elements())
                {
                    //各字段
                    string fullName = cla.Attribute(XName.Get("fullName")).Value;
                    string classDesc = cla.Attribute(XName.Get("desc")).Value;
                    info.WriteHost = write;

                    if (dics.ContainsKey(fullName) == false)
                    {
                        dics.Add(fullName, info);
                    }
                }

                if (DefaultConfigHost==null||info.isDefault)
                {
                    DefaultConfigHost = info;
                }
               
            }

            //如果没有默认配置  默认配置设置为不启用
            DefaultConfigHost = DefaultConfigHost ?? new ConfigHost() { Type= CaCheType.No };

            return dics;
        }
    }
}
